<template>
  <div class="chart-container">
    <div class="chart-header">
      <h3>销售趋势与预测</h3>
      <el-radio-group v-model="chartType" size="small">
        <el-radio-button label="line">折线图</el-radio-button>
        <el-radio-button label="bar">柱状图</el-radio-button>
      </el-radio-group>
    </div>
    
    <div class="chart-content" :class="{ 'is-loading': loading }">
      <div ref="chartRef" class="echarts-wrapper"></div>
      <div v-if="loading" class="loading-overlay">
        <el-skeleton animated :rows="5" />
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, shallowRef, onMounted, onUnmounted, watch } from 'vue';
import * as echarts from 'echarts/core';
import { LineChart, BarChart } from 'echarts/charts';
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  DataZoomComponent,
  LegendComponent,
  MarkAreaComponent
} from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';

// 注册必要的组件
echarts.use([
  TitleComponent,
  TooltipComponent,
  GridComponent,
  DataZoomComponent,
  LegendComponent,
  MarkAreaComponent,
  LineChart,
  BarChart,
  CanvasRenderer
]);

const props = defineProps({
  salesData: {
    type: Array,
    default: () => []
  },
  prediction: {
    type: Number,
    default: null
  },
  upperBound: {
    type: Number,
    default: null
  },
  lowerBound: {
    type: Number,
    default: null
  },
  nextMonth: {
    type: String,
    default: ''
  },
  loading: {
    type: Boolean,
    default: false
  }
});

const chartRef = ref(null);
const chart = shallowRef(null);
const chartType = ref('line');
let resizeObserver = null;

// 监听数据变化，更新图表
watch([() => props.salesData, () => props.prediction, () => props.nextMonth, chartType], 
  () => {
    if (chart.value && props.salesData?.length > 0) {
      updateChart();
    }
  }, 
  { deep: true }
);

// 监听加载状态
watch(() => props.loading, (newVal) => {
  if (!newVal && chart.value) {
    updateChart();
  }
});

onMounted(() => {
  if (chartRef.value) {
    initChart();
    
    // 监听窗口大小变化，添加节流函数以避免频繁触发
    const resizeHandler = () => {
      if (chart.value) {
        chart.value.resize();
      }
    };
    
    // 使用防抖函数处理resize事件
    const debouncedResize = debounce(resizeHandler, 100);
    
    resizeObserver = new ResizeObserver(() => {
      debouncedResize();
    });
    resizeObserver.observe(chartRef.value);
  }
});

onUnmounted(() => {
  // 销毁图表实例
  if (chart.value) {
    chart.value.dispose();
    chart.value = null;
  }
  
  // 清除resize观察者
  if (resizeObserver) {
    resizeObserver.disconnect();
    resizeObserver = null;
  }
});

// 初始化图表
function initChart() {
  if (!chartRef.value) return;
  
  // 确保图表容器有固定高度
  const container = chartRef.value;
  if (!container.style.height || container.style.height === 'auto') {
    container.style.height = '400px';
  }
  
  chart.value = echarts.init(chartRef.value);
  updateChart();
}

// 更新图表数据
function updateChart() {
  if (!chart.value || props.loading) return;
  
  // 准备数据
  const months = props.salesData.map(item => item.month);
  const amounts = props.salesData.map(item => item.amount);
  
  // 添加预测点
  if (props.prediction && props.nextMonth) {
    months.push(props.nextMonth);
    amounts.push(null); // 先设置为null，在series中通过connectNulls连接
  }
  
  // 设置图表选项
  const option = {
    backgroundColor: 'transparent',
    title: {
      show: false
    },
    tooltip: {
      trigger: 'axis',
      backgroundColor: 'rgba(19, 20, 42, 0.9)',
      borderColor: 'rgba(42, 42, 87, 0.8)',
      textStyle: {
        color: '#e0e0ff'
      },
      formatter: function(params) {
        const dataIndex = params[0].dataIndex;
        if (dataIndex === months.length - 1 && props.prediction) {
          // 预测点的tooltip
          return `
            <div style="padding: 5px">
              <div style="font-weight: bold; margin-bottom: 5px">${props.nextMonth} (预测)</div>
              <div>预测销售额: ¥${props.prediction.toLocaleString('zh-CN', {
                minimumFractionDigits: 2,
                maximumFractionDigits: 2
              })}</div>
              <div style="margin-top: 5px; font-size: 12px; color: #7171a6;">
                置信区间: ¥${props.lowerBound.toLocaleString('zh-CN', {
                  minimumFractionDigits: 2,
                  maximumFractionDigits: 2
                })} - ¥${props.upperBound.toLocaleString('zh-CN', {
                  minimumFractionDigits: 2,
                  maximumFractionDigits: 2
                })}
              </div>
            </div>
          `;
        } else {
          // 历史数据点的tooltip
          const item = props.salesData[dataIndex];
          return `
            <div style="padding: 5px">
              <div style="font-weight: bold; margin-bottom: 5px">${item.month}</div>
              <div>销售额: ¥${item.amount.toLocaleString('zh-CN', {
                minimumFractionDigits: 2,
                maximumFractionDigits: 2
              })}</div>
            </div>
          `;
        }
      }
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '10%',
      top: '10%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      data: months,
      boundaryGap: chartType.value === 'bar',
      axisLine: {
        lineStyle: {
          color: 'rgba(113, 113, 166, 0.3)'
        }
      },
      axisLabel: {
        color: '#7171a6',
        formatter: function(value) {
          // 只显示月份，如2023-01 => 1月
          if (value.includes('-')) {
            const month = parseInt(value.split('-')[1]);
            return `${month}月`;
          }
          return value;
        }
      },
      axisTick: {
        alignWithLabel: true,
        lineStyle: {
          color: 'rgba(113, 113, 166, 0.3)'
        }
      }
    },
    yAxis: {
      type: 'value',
      axisLine: {
        show: false
      },
      axisLabel: {
        color: '#7171a6',
        formatter: function(value) {
          if (value >= 1000000) {
            return (value / 1000000).toFixed(1) + 'M';
          } else if (value >= 1000) {
            return (value / 1000).toFixed(0) + 'K';
          }
          return value;
        }
      },
      splitLine: {
        lineStyle: {
          color: 'rgba(113, 113, 166, 0.1)'
        }
      }
    },
    dataZoom: [
      {
        type: 'inside',
        start: Math.max(0, 100 - (800 / months.length)),
        end: 100
      }
    ],
    series: getChartSeries()
  };
  
  chart.value.setOption(option, true);
}

// 根据图表类型生成不同的series配置
function getChartSeries() {
  if (chartType.value === 'line') {
    return getLineSeries();
  } else {
    return getBarSeries();
  }
}

// 生成折线图series
function getLineSeries() {
  const series = [
    {
      name: '历史销售额',
      type: 'line',
      data: props.salesData.map(item => item.amount),
      smooth: true,
      symbolSize: 6,
      lineStyle: {
        width: 3,
        color: {
          type: 'linear',
          x: 0,
          y: 0,
          x2: 0,
          y2: 1,
          colorStops: [
            { offset: 0, color: '#3a36db' },
            { offset: 1, color: '#00c9ff' }
          ]
        }
      },
      itemStyle: {
        color: '#00c9ff',
        borderColor: '#fff',
        borderWidth: 2
      },
      connectNulls: true
    }
  ];
  
  // 添加预测点
  if (props.prediction && props.nextMonth) {
    // 克隆一份历史销售数据
    const predictionData = [...props.salesData.map(item => item.amount)];
    // 添加预测点
    predictionData.push(props.prediction);
    
    series.push({
      name: '预测销售额',
      type: 'line',
      data: predictionData.slice(-2), // 只显示最后一个历史点和预测点
      lineStyle: {
        width: 3,
        type: 'dashed',
        color: '#00ffb3'
      },
      itemStyle: {
        color: '#00ffb3',
        borderColor: '#fff',
        borderWidth: 2
      },
      symbolSize: 8,
      symbol: 'circle',
      connectNulls: true,
      markArea: {
        itemStyle: {
          color: 'rgba(0, 255, 179, 0.1)',
          borderColor: 'rgba(0, 255, 179, 0.3)',
          borderWidth: 1
        },
        data: [[
          { 
            xAxis: props.salesData.length - 1,
            yAxis: props.lowerBound
          },
          {
            xAxis: props.salesData.length,
            yAxis: props.upperBound
          }
        ]]
      }
    });
  }
  
  return series;
}

// 生成柱状图series
function getBarSeries() {
  const series = [
    {
      name: '历史销售额',
      type: 'bar',
      data: props.salesData.map(item => item.amount),
      barWidth: '40%',
      itemStyle: {
        color: {
          type: 'linear',
          x: 0,
          y: 0,
          x2: 0,
          y2: 1,
          colorStops: [
            { offset: 0, color: '#3a36db' },
            { offset: 1, color: '#00c9ff' }
          ]
        },
        borderRadius: [4, 4, 0, 0]
      }
    }
  ];
  
  // 添加预测柱
  if (props.prediction && props.nextMonth) {
    // 克隆一份历史销售数据并填充null
    const historyData = [...props.salesData.map(item => item.amount)];
    historyData.push(null);
    
    // 预测数据全部为null，只有最后一个点有值
    const predictionData = Array(props.salesData.length).fill(null);
    predictionData.push(props.prediction);
    
    series[0].data = historyData;
    
    series.push({
      name: '预测销售额',
      type: 'bar',
      data: predictionData,
      barWidth: '40%',
      itemStyle: {
        color: {
          type: 'linear',
          x: 0,
          y: 0,
          x2: 0,
          y2: 1,
          colorStops: [
            { offset: 0, color: '#00ffe7' },
            { offset: 1, color: '#00ffb3' }
          ]
        },
        borderRadius: [4, 4, 0, 0]
      }
    });
    
    // 添加预测区间的errorbar
    series.push({
      name: '预测区间',
      type: 'custom',
      renderItem: function(params, api) {
        if (params.dataIndex !== predictionData.length - 1) {
          return;
        }
        
        const xValue = api.value(0);
        const highPoint = api.coord([xValue, props.upperBound]);
        const lowPoint = api.coord([xValue, props.lowerBound]);
        const midPoint = api.coord([xValue, props.prediction]);
        
        const barWidth = api.size([1, 0])[0] * 0.4;
        const halfWidth = barWidth / 2;
        
        return {
          type: 'group',
          children: [
            // 垂直线
            {
              type: 'line',
              shape: {
                x1: midPoint[0],
                y1: highPoint[1],
                x2: midPoint[0],
                y2: lowPoint[1]
              },
              style: {
                stroke: 'rgba(0, 255, 179, 0.7)',
                lineWidth: 2
              }
            },
            // 上横线
            {
              type: 'line',
              shape: {
                x1: midPoint[0] - halfWidth,
                y1: highPoint[1],
                x2: midPoint[0] + halfWidth,
                y2: highPoint[1]
              },
              style: {
                stroke: 'rgba(0, 255, 179, 0.7)',
                lineWidth: 2
              }
            },
            // 下横线
            {
              type: 'line',
              shape: {
                x1: midPoint[0] - halfWidth,
                y1: lowPoint[1],
                x2: midPoint[0] + halfWidth,
                y2: lowPoint[1]
              },
              style: {
                stroke: 'rgba(0, 255, 179, 0.7)',
                lineWidth: 2
              }
            }
          ]
        };
      },
      data: predictionData
    });
  }
  
  return series;
}

// 防抖函数
function debounce(fn, delay) {
  let timer = null;
  return function() {
    const context = this;
    const args = arguments;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.apply(context, args);
    }, delay);
  };
}
</script>

<style scoped>
.chart-container {
  background-color: var(--bg-card, #13142a);
  border-radius: 8px;
  border: 1px solid var(--border-color, #2a2a57);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
  overflow: hidden;
  height: 100%;
  max-height: 100%;
  display: flex;
  flex-direction: column;
}

.chart-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-color, #2a2a57);
}

.chart-header h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary, #e0e0ff);
}

.chart-content {
  flex: 1;
  position: relative;
  min-height: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.chart-content.is-loading {
  opacity: 0.7;
}

.echarts-wrapper {
  width: 100%;
  flex: 1;
  min-height: 0;
  height: 100%;
}

.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(19, 20, 42, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  padding: 20px;
}
</style> 